//
// CustomFlipper.java : authorized by @visualkhh : visualkhh@gmail.com
//
// Modifed By astro666@hanmail.net(http://blog.daum.net/aero2k)
//

package com.tw.bjkim;


import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;


public class HorizontalFlingerLayout extends FrameLayout 
{
	public HorizontalFlingerLayout(Context context)
	{
		super(context);
		this.context = context;
		init();
	}

	public HorizontalFlingerLayout(Context context, AttributeSet attrs) 
	{
		super(context, attrs);
		this.context = context;
		init();
	}
	
	public HorizontalFlingerLayout(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
		this.context = context;
		init();
	}
	
	private void init()
	{
		// 1. HorizontalScrollView ´Â Content ItemµéÀ» ´ãÀ» Container ÀÌ´Ù.
		content_horizontal_container = new HorizontalScrollView(context);
		content_horizontal_container.setHorizontalFadingEdgeEnabled(false);
		content_horizontal_container.setHorizontalScrollBarEnabled(false);	// ÇÏ´Ü¹ÙÀÇ scroll »óÅÂ¹Ù¸¦ Á¦°ÅÇÒ¶§ »ç¿ëÇÑ´Ù.
		content_horizontal_container.setLayoutParams(new ViewGroup.LayoutParams(
				ViewGroup.LayoutParams.FILL_PARENT,
				ViewGroup.LayoutParams.FILL_PARENT));
		
		// 2. °¢°¢ÀÇ ÆäÀÌÁö ¸¶´Ù Content Item(View)µéÀ» ´ãÀ» Container ÀÌ´Ù.
		// addView() ÇÔ¼öÀ» ÀÌ¿ëÇØ¼­ View µéÀ» Ãß°¡ ÇÑ´Ù.
		content_item_container = new LinearLayout(context);
		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
				ViewGroup.LayoutParams.FILL_PARENT,
				ViewGroup.LayoutParams.FILL_PARENT,
				0.0F);
		params.leftMargin = 0;
		params.rightMargin = 0;
		params.topMargin = 0;
		params.bottomMargin = 0;
		//params.gravity = Gravity.CENTER;
		content_item_container.setLayoutParams(params);
		content_item_container.setGravity(Gravity.CENTER);
		content_item_container.setOrientation(LinearLayout.HORIZONTAL);
		
		
		// 3. ÇÏ³ªÀÇ ÆäÀÌÁö¸¦ °¨½Î´Â Layout Container·Î¼­ content_item_container¸¦ ´ã´Â´Ù.
		// ÀÌ container °´Ã¼´Â HorizontalScrollView¿¡ Ãß°¡ µÈ´Ù.
		container = new LinearLayout(context);
		LinearLayout.LayoutParams params_container = new LinearLayout.LayoutParams(
				ViewGroup.LayoutParams.FILL_PARENT, 
				ViewGroup.LayoutParams.FILL_PARENT, 
				0.0F);
		params_container.leftMargin = 0;
		params_container.rightMargin = 0;
		params_container.topMargin = 0;
		params_container.bottomMargin = 0;
		container.setLayoutParams(params_container);
		container.setGravity(Gravity.CENTER);
		container.setOrientation(LinearLayout.HORIZONTAL);
		
		// "2." ¹ø content_item_container ´Â  "3."¹ø  container¿¡ Ãß°¡ ÇÑ´Ù.
		// "3." ¹ø container´Â "1."¹ø content_horizontal_container¿¡ Ãß°¡ ÇÑ´Ù.
		container.addView(content_item_container);
		
		content_horizontal_container.addView(container);
		content_horizontal_container.setOnTouchListener(onTouchListener);
		
		// ÃÖÁ¾ HorizontalScrollView¸¦ FrameLayout¿¡ Ãß°¡ÇÑ´Ù.
		super.addView(content_horizontal_container);
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		for (int i = 0; i < getContentChildCount(); i++)
		{
			View atChild = content_item_container.getChildAt(i);
			LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)atChild.getLayoutParams();
			params.width = getMeasuredWidth();
			params.height = getMeasuredHeight();
			atChild.setLayoutParams(params);
		}
		
		LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) content_item_container.getLayoutParams();
		params.width = (int) getContentWidth();
		params.height = (int) getMeasuredHeight();

		content_item_container.setLayoutParams(params);
		
		int currIndex = getIndex();
		
		switch (interpolationMode) {
		case (HelperFunction.INTERPOLATION_EASEOUT):
			nextPageDividedEaseOut(currIndex);
			break;
		
		case (HelperFunction.INTERPOLATION_EULER_EASEOUT):
			nextPageBasedEulerEaseOut(currIndex);
			break;
			
		case (HelperFunction.INTERPOLATION_EASEINOUT):
			nextPageInterpolationEaseInOut(currIndex);
			break;
		}
		
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	// °¢°¢ÀÇ ÆäÀÌÁö ¸¶´Ù Content Item(View)µéÀ» ´ãÀ» Container ÀÌ´Ù.
	@Override
	public void addView(View child)
	{
		LinearLayout atContainer = new LinearLayout(context);
		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
				ViewGroup.LayoutParams.FILL_PARENT, 
				ViewGroup.LayoutParams.FILL_PARENT, 
				0.0F);
		int pading = 0;
		params.leftMargin = pading;
		params.rightMargin = pading;
		params.topMargin = pading;
		params.bottomMargin = pading;
		atContainer.setLayoutParams(params);
		atContainer.setGravity(Gravity.CENTER);
		atContainer.setOrientation(LinearLayout.VERTICAL);
		atContainer.addView(child);
		
		content_item_container.addView(atContainer);
	}
	
	public void addView(View top, View middle, View bottom)
	{
		LinearLayout atContainer = new LinearLayout(context);
		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
				ViewGroup.LayoutParams.FILL_PARENT, 
				ViewGroup.LayoutParams.FILL_PARENT, 
				0.0F);
		int pading = 0;
		params.leftMargin = pading;
		params.rightMargin = pading;
		params.topMargin = pading;
		params.bottomMargin = pading;
		params.gravity = Gravity.TOP;
		atContainer.setLayoutParams(params);
		atContainer.setGravity(Gravity.TOP);
		atContainer.setOrientation(LinearLayout.VERTICAL);
		atContainer.addView(top);
		atContainer.addView(middle);
		atContainer.addView(bottom);
		
		content_item_container.addView(atContainer);
	}
	//

	// For Touch Listener
	float moveAction_x = -1.0f;
	float moveAction_y = -1.0f;
	float downAction_x = 0;
	float downAction_y = 0;
	
	long downTime = 0;
	long upTime = 0;
	
	OnTouchListener onTouchListener = new OnTouchListener()
	{

		@Override
		public boolean onTouch(View v, MotionEvent event) 
		{
			int action = event.getAction();
			
			if (D)
				Log.d(TAG, "onTouch - GetAction : " + action);
			
			if (action == event.ACTION_DOWN) 
			{
				// »ç¿ëÀÚ°¡ °¡¸¸È÷ ´©¸¥ »óÅÂ¿¡¼­ ÀÌµ¿À» ÇÒ °æ¿ì¿¡´Â dTÀÇ intervalÀÇ ±æ¾îÁø´Ù.
				// ±×·³À¸·Î, ¸ðµç ´Ù¿î Ã³¸®¿¡ ´ëÇÑ ÆÇ´ÜÀº ACTION_MOVE¿¡¼­ ÇÏµµ·Ï ÇÏÀÚ.
				if (D)
					Log.d(TAG, "onTouch - Down(X) : " + event.getX() +  "Down(Y) : " + event.getY());
				
				return true;				
			} else if (action == event.ACTION_UP)
			{
				upTime = System.currentTimeMillis();
				long dT = Math.abs(upTime - downTime);
				float dX = downAction_x - event.getX();
				int currIndex = getNeighborIndex();
				
				if (D) {
					Log.d(TAG2, "onTouch - Up moveAction_x:" + moveAction_x);
					Log.d(TAG2, "onTouch - Up dT:" + dT + "    dV:" + dX);
				}
				
				if (dT < accelerationDelay_ms) 
				{
					if (dX > 15) 
					{
						// ¿À¸¥ÂÊÀ¸·Î  ÀÌµ¿
						currIndex = m_nIndex;
						currIndex++;
					} else if (dX < -15) 
					{
						// ¿ÞÂÊÀ¸·Î ÀÌµ¿.
						currIndex = m_nIndex;
						currIndex--;
					}
				}
				
				if (D) {
					Log.d(TAG2, "onTouch - dT"+ dT + " Up(X) : " + event.getX() +  "Up(Y) : " + event.getY());
				}
				
				switch (interpolationMode) {
				case (HelperFunction.INTERPOLATION_EASEOUT):
					nextPageDividedEaseOut(currIndex);
					break;
				
				case (HelperFunction.INTERPOLATION_EULER_EASEOUT):
					nextPageBasedEulerEaseOut(currIndex);
					break;
					
				case (HelperFunction.INTERPOLATION_EASEINOUT):
					nextPageInterpolationEaseInOut(currIndex);
					break;
				}
				
				moveAction_x = -1.0f;
				
				return true;
			} else if (action == event.ACTION_MOVE)
			{
				if (D)
					Log.d(TAG, "onTouch - Move : old(" + moveAction_x +")   new(" + event.getX() + ")");
				
				if (moveAction_x == -1.0f) {
					moveAction_x = event.getX();
					downAction_x = event.getX();
					downTime = System.currentTimeMillis();
				}
				
				float dV = moveAction_x - event.getX();
				moveAction_x = event.getX();
				
				setHorizontalView_append_x(dV);
				return true;
			}
			
			return false;
		}
		
	};
	//
	
	// For processing interpolation method.
	private int interpolationMode;
	
	public int getIndex() {
		return m_nIndex;
	}
	
	public void setInterpolationMode(int interpolationMode)
	{
		this.interpolationMode = interpolationMode;
	}
	
	// DividedEaseOut ±â¹ÝÀÇ °¨¼Ó º¸°£¹ý
	// GPG Gems vol 1 - 2.1 º¸°£ ¹ý : ºÎµ¿¼Ò¼öÁ¡ ¿¬»êÀ» ÀÌ¿ëÇÑ ÇÁ·¹ÀÓÀ² ÀÇÁ¸ÀûÀÎ °¨¼Ó º¸°£
	public void nextPageDividedEaseOut(int inputIndex)
	{
		long tm = System.currentTimeMillis();
		
		// ÃÖ¼Ò °ª °æ°è
		if (inputIndex < 0) {
			inputIndex = 0;
		}
		
		// ÃÖ´ë °ª °æ°è
		if (inputIndex >= getContentChildCount()) {
			inputIndex = getContentChildCount() - 1;
		}
		
		final int index = inputIndex;
		
		Thread threadDividedEaseOut = new Thread() {
			public void run() 
			{
				int step = 60;
				//
				// For interpolation.
				// index : ¸î¹øÂ° ÆäÀÌÁöÀÎÁö ³ªÅ¸³½´Ù. Ã¹ÆäÀÌÁö´Â 0 / µÎ¹øÂ° ÆäÀÌÁö´Â 1ÀÌ´Ù. 
				// getMeasuredWidth() : GalaxySÀÇ °æ¿ì, 480ÀÌ´Ù. : 480x800 : GalaxyTabÀÇ °æ¿ì, 600x1024
				// getHorizontal_x() : Left·ÎºÎÅÍ ÀÌ¹Ì ½ºÅ©·ÑµÈ ÁÂÇ¥
				//
				// Example
				// µÎ ¹øÂ° ÆäÀÌÁö¿¡¼­ ÀÌ¹Ì 291¸¸Å­ ÁÂ¿¡¼­ ¿ì·Î ScrollÀÌ µÇ¾ú´Ù¸é, 
				// chartWidth = (1 * 480) - 291 = 189 ¸¸Å­ ÀÌµ¿ÀÌ ³²Àº »óÅÂÀÌ´Ù.

				int interpolation_index = 0;
				float[] interpolation_values = new float[step];
				float weight = 8.0f;
				float x0 = 0.0f;
				float x1 = 0.0f;
				final float x_final = (index * getMeasuredWidth()) - getHorizontal_x();
				
				// EaseOut °¨¼Ó º¸°£ ¼ö½Ä.
				x0 = (x0*(weight-1)+x_final)/weight;
				interpolation_values[interpolation_index++] = x0;
				
				// ¼Õ°¡¶ôÀ» ¶¾ ½ÃÁ¡(ACTION_UP)ÀÇ ÁÂÇ¥¸¦ ±âÁØÀ¸·Î ÇÏ¿©, º¸°£ Ã³¸®ÇÒ ÁÂÇ¥¸¦ »ý¼ºÇÑ´Ù.
				do {
					if (x_final >= 0) {
						if (x0 >= x_final-1) {
							interpolation_values[interpolation_index] = 0;
							break;
						}
					} else {
						if (Math.abs(x0) >= Math.abs(x_final)-1) {
							interpolation_values[interpolation_index] = 0;
							break;
						}
					}
					
					x1 = (x0*(weight-1)+x_final)/weight;
					
					interpolation_values[interpolation_index++] = (x1 - x0);
					x0 = x1;
				} while(interpolation_index <= step);
				
				// Thread.sleep(5ms) ¸¶´Ù ½¬¸é¼­ °¨¼Ó º¸°£À» ¼öÇàÇÑ´Ù.
				for (int i=0; i<interpolation_index; i++) {
					final double x_pos = interpolation_values[i];
					
					if (D)
						Log.d(TAG2, "index:" + i + " x_pos:" + x_pos);
					
					handler.post(new Runnable() {
						@Override
						public void run() {
							setHorizontalView_append_x(x_pos);
						}
					});
					
					try {
						sleep(5);
					} catch (InterruptedException ie) {
						ie.printStackTrace();
					}
				}
					
				handler.post(new Runnable() {
					@Override
					public void run() {
						
						if (D) {
							Log.e(TAG, "Interpolation Done:" + (System.currentTimeMillis() - tm_interpolation) + "ms");
						}
						
						// ÆäÀÌÁöÀÇ ³Êºñ ¿Í ÀÎµ¦½º ÀúÀå.
						setHorizontalView_abs_x(index * getMeasuredWidth());
						setIndex(index);
					}
				});
			}
		};
		
		if (D) {
			tm_interpolation = System.currentTimeMillis();
		}
		
		threadDividedEaseOut.start();
		
		if (D) {
			Log.e(TAG, "nextIndexPageBasedFrameInterval:" + (System.currentTimeMillis() - tm) + "ms");
		}
	}

	// ¿ÀÀÏ·¯ ¼ö e ±â¹ÝÀÇ °¡ÁßÄ¡ º¸°£¹ý
	public void nextPageBasedEulerEaseOut(int inputIndex)
	{
		long tm = System.currentTimeMillis();
		
		// ÃÖ¼Ò °ª °æ°è
		if (inputIndex < 0) {
			inputIndex = 0;
		}
		
		// ÃÖ´ë °ª °æ°è
		if (inputIndex >= getContentChildCount()) {
			inputIndex = getContentChildCount() - 1;
		}
		
		final int index = inputIndex;
		
		Thread threadEulerInterpolation = new Thread() {
			public void run() 
			{
				int step = 40;
				double[] exp = new double[step];
				double sum = 0;
				double interpolation_wi = 0.15;
				
				// Euler number ÀÚ¿¬·Î±× ¼ö¸¦ ÀÌ¿ëÇÏ¿©, º¸°£ Ã³¸®ÇÑ ÁÂÇ¥¸¦ 40°³ »ý¼ºÇÑ´Ù.
				for (int i=0; i<step; i++) {
					double expVal = Math.exp(-(interpolation_wi*(i+1)));	// ÃÖ´ë °ª¿¡¼­ ±Þ°ÝÈ÷ °¨¼Ò ÇÏ´Ù°¡ ¼­¼­È÷ °¨¼Ò
//					double expVal = Math.exp((interpolation_wi*(i+1)));		// ÃÖ¼Ò °ª¿¡¼­ ¼­¼­È÷ Áõ°¡ ÇÏ´Ù°¡  ±Þ°ÝÈ÷ Áõ°¡
					exp[i] = expVal;
					sum += expVal;
					
					if (D)
						Log.d(TAG, "expVal(" + i + "):" + exp[i] + "    sum:" + sum);
				}
				
				for (int i=0; i<step; i++) {
					exp[i] = exp[i] / sum;
					
					if (D)
						Log.d(TAG, "expVal/sum(" + i + "):" + exp[i] + "    sum:" + sum);
				}
				//
				
				//
				// For interpolation.
				// index : ¸î¹øÂ° ÆäÀÌÁöÀÎÁö ³ªÅ¸³½´Ù. Ã¹ÆäÀÌÁö´Â 0 / µÎ¹øÂ° ÆäÀÌÁö´Â 1ÀÌ´Ù. 
				// getMeasuredWidth() : GalaxySÀÇ °æ¿ì, 480ÀÌ´Ù. : 480x800 : GalaxyTabÀÇ °æ¿ì, 600x1024
				// getHorizontal_x() : Left·ÎºÎÅÍ ÀÌ¹Ì ½ºÅ©·ÑµÈ ÁÂÇ¥
				//
				// Example
				// µÎ ¹øÂ° ÆäÀÌÁö¿¡¼­ ÀÌ¹Ì 291¸¸Å­ ÁÂ¿¡¼­ ¿ì·Î ScrollÀÌ µÇ¾ú´Ù¸é, 
				// chartWidth = (1 * 480) - 291 = 189 ¸¸Å­ ÀÌµ¿ÀÌ ³²Àº »óÅÂÀÌ´Ù.
				final float x_final = (index * getMeasuredWidth()) - getHorizontal_x();
				
				// Thread.sleep(5ms) ¸¶´Ù ½¬¸é¼­ °¨¼Ó º¸°£À» ¼öÇàÇÑ´Ù.
				for (int i=0; i<step; i++) {
					final double x_pos = x_final * exp[i];
					
					if (D)
						Log.d(TAG2, "index:" + i + " chartWidth:" + x_final + "    expVal:" + exp[i] + "    x_pos:" + x_pos);
					
					handler.post(new Runnable() {
						@Override
						public void run() {
							setHorizontalView_append_x(x_pos);
						}
					});
					
					try {
						sleep(5);
					} catch (InterruptedException ie) {
						ie.printStackTrace();
					}
				}
					
				handler.post(new Runnable() {
					@Override
					public void run() {
						
						if (D) {
							Log.e(TAG, "Interpolation Done:" + (System.currentTimeMillis() - tm_interpolation) + "ms");
						}
						
						setHorizontalView_abs_x(index * getMeasuredWidth());
						setIndex(index);
					}
				});
			}
		};
		
		if (D) {
			tm_interpolation = System.currentTimeMillis();
		}
		
		threadEulerInterpolation.start();
		
		if (D) {
			Log.e(TAG, "nextIndexPageBasedEulerNumber:" + (System.currentTimeMillis() - tm) + "ms");
		}
	}
	
	// Ease In Ease Out ±â¹ÝÀÇ °¡-°¨¼Ó º¸°£¹ý
	// GPG Gems vol 1 - 2.1 º¸°£ ¹ý : ÇÁ·¹ÀÓÀ² µ¶¸³ÀûÀÎ °¡-°¨¼Ó º¸°£
	public void nextPageInterpolationEaseInOut(int inputIndex)
	{
		long tm = System.currentTimeMillis();
		
		// ÃÖ¼Ò °ª °æ°è
		if (inputIndex < 0) {
			inputIndex = 0;
		}
		
		// ÃÖ´ë °ª °æ°è
		if (inputIndex >= getContentChildCount()) {
			inputIndex = getContentChildCount() - 1;
		}
		
		final int index = inputIndex;
		
		Thread threadEaseInOut = new Thread() {
			public void run() 
			{
				int step = 60;
				//
				// For interpolation.
				// index : ¸î¹øÂ° ÆäÀÌÁöÀÎÁö ³ªÅ¸³½´Ù. Ã¹ÆäÀÌÁö´Â 0 / µÎ¹øÂ° ÆäÀÌÁö´Â 1ÀÌ´Ù. 
				// getMeasuredWidth() : GalaxySÀÇ °æ¿ì, 480ÀÌ´Ù. : 480x800 : GalaxyTabÀÇ °æ¿ì, 600x1024
				// getHorizontal_x() : Left·ÎºÎÅÍ ÀÌ¹Ì ½ºÅ©·ÑµÈ ÁÂÇ¥
				//
				// Example
				// µÎ ¹øÂ° ÆäÀÌÁö¿¡¼­ ÀÌ¹Ì 291¸¸Å­ ÁÂ¿¡¼­ ¿ì·Î ScrollÀÌ µÇ¾ú´Ù¸é, 
				// chartWidth = (1 * 480) - 291 = 189 ¸¸Å­ ÀÌµ¿ÀÌ ³²Àº »óÅÂÀÌ´Ù.
				
				float x0 = 0.0f;	// x0 : from, x_final : to
				float x1 = 0.0f;	// delta X¸¦ ±¸ÇÏ±â À§ÇØ¼­ Ãß°¡.
				
				// °¡¼Óµµ a = (to - from) / (time * time / 2) ÀÇ ¼ö½ÄÀÌÁö¸¸,
				// EaseInOutÀº °¡¼Ó ÇÏ´Ù°¡ Áß°£ À§Ä¡¿¡¼­ °¨¼Ó Ã³¸®¸¦ ÇØÁà¾ß ÇÔÀ¸·Î ±æÀÌ°¡ µÎ¹è°¡ µÇ¾î¾ß ÇÑ´Ù.
				// ÀÌ¶§¹®¿¡ (time * time / 4) ·Î À¯µµ µÇ¾ú´Ù.
				final float x_final = (index * getMeasuredWidth()) - getHorizontal_x();
				final float time = 10.0f;
				final float acceleration = (x_final - x0) / (time * time / 4);

				// °¡ °¨¼Ó º¸°£Àº ½Ã°£ º¯È­·®¿¡ µû¸¥ °¡¼Óµµ °ªÀ» ±¸ÇÑ´Ù.
				// ÀÌ ¿¹Á¦¿¡¼­´Â ½Ã°£ º¯È­·® time¸¦ °íÁ¤ ÇÏ¿´À¸¸ç, Frame ÀÇÁ¸ÀûÀ¸·Î µ¿ÀÛÇÑ´Ù.
				int interpolation_index = 0;
				float[] interpolation_values = new float[step+1];
				
				float deltaT = 10.0f / (float)step;
				float velocity = 0.0f;
				float remainingTime = time - deltaT;
				
				// EaseInOut º¸°£ ¼ö½Ä : value = x + (velocity * deltaT)
				// °¡¼Óµµ¿¡¼­ 2Áß ÀûºÐ ÇÏ¸é °Å¸®¸¦ ±¸ÇÒ¼ö ÀÖ´Ù.
				velocity = (acceleration * deltaT);
				x1 = (velocity * deltaT);
				
				interpolation_values[interpolation_index++] = x1;
				
				// ¼Õ°¡¶ôÀ» ¶¾ ½ÃÁ¡(ACTION_UP)ÀÇ ÁÂÇ¥¸¦ ±âÁØÀ¸·Î ÇÏ¿©, º¸°£ Ã³¸®ÇÒ ÁÂÇ¥¸¦ »ý¼ºÇÑ´Ù.
				do {
					if (remainingTime > time/2) {
						// °¡¼Ó Ã³¸®
						velocity += (acceleration * deltaT);
					} else {
						// °¨¼Ó Ã³¸®
						velocity -= (acceleration * deltaT);
					}
					
					x1 += (velocity * deltaT);
					
					interpolation_values[interpolation_index++] = (x1 - x0);
					x0 = x1;
//					interpolation_index++;
					
					remainingTime -= deltaT;
				} while(remainingTime > 0.0f);
				
				// Thread.sleep(5ms) ¸¶´Ù ½¬¸é¼­ °¨¼Ó º¸°£À» ¼öÇàÇÑ´Ù.
				for (int i=0; i<interpolation_index; i++) {
					final double x_pos = interpolation_values[i];
					
					if (D)
						Log.d(TAG2, "index:" + i + " x_pos:" + x_pos);
					
					handler.post(new Runnable() {
						@Override
						public void run() {
							setHorizontalView_append_x(x_pos);
						}
					});
					
					try {
						sleep(5);
					} catch (InterruptedException ie) {
						ie.printStackTrace();
					}
				}
					
				handler.post(new Runnable() {
					@Override
					public void run() {
						
						if (D) {
							Log.e(TAG, "Interpolation Done:" + (System.currentTimeMillis() - tm_interpolation) + "ms");
						}
						
						// ÆäÀÌÁöÀÇ ³Êºñ ¿Í ÀÎµ¦½º ÀúÀå.
						setHorizontalView_abs_x(index * getMeasuredWidth());
						setIndex(index);
					}
				});
			}
		};
		
		if (D) {
			tm_interpolation = System.currentTimeMillis();
		}
		
		threadEaseInOut.start();
		
		if (D) {
			Log.e(TAG, "nextPageInterpolationEaseInOut:" + (System.currentTimeMillis() - tm) + "ms");
		}
	}
	// For Linear Interpolation.

	//
	// Background Image ÀúÀå
	//
	public void setBackgroundResourceContent(int rsc){
		content_item_container.setBackgroundResource(rsc);
	}
	public void setBackgroundDrawableContent(Drawable draw){
		content_item_container.setBackgroundDrawable(draw);
	}
	public void setBackgroundColorContent(int color){
		content_item_container.setBackgroundColor(color);
	}
	//
	
	//
	// Setter
	//
	private void setIndex(int index) {
		m_nIndex = index;
	}
	private void setHorizontalView_abs_x(int value) {
		content_horizontal_container.scrollTo(value, content_horizontal_container.getScrollY());
		content_horizontal_container.invalidate();
	}
	private void setHorizontalView_append_x(double value) {
		int x = content_horizontal_container.getScrollX() + (int)value;
		int y = content_horizontal_container.getScrollY();
		
		if (D) {
			Log.d(TAG, "content_horizontal_container.getScrollX():" +
					content_horizontal_container.getScrollX() +
					"  v:" + (int)value);
		}

		// HorizontalView¸¦ x, y ÁÂÇ¥ ¸¸Å­ ÀÌµ¿.
		content_horizontal_container.scrollTo(x, y);
	}
	//
	
	//
	// Getter
	//
	private float getContentWidth() {
		float inner_full_width = 0.0f;
		inner_full_width = getMeasuredWidth() * getContentChildCount();	// ÀüÃ¼ ¿µ¿ª Å©±â
		return inner_full_width;
	}
	private float getHorizontal_x() {
		return content_horizontal_container.getScrollX();
	}
	private int getContentChildCount() {
		return content_item_container.getChildCount();
	}
	private int getNeighborIndex() 
	{
		float at_view_point = getViewCenterPoint();	// »ç¿ëÀÚ°¡ º¸°í ÀÖ´Â À§Ä¡ : (¸Ç ¿ÞÂÊ + Àý¹Ý Å©±â)
		float horizontal_child_count = getContentChildCount();
		int currIndex = 0;
		
		for (int i = 0; i < horizontal_child_count; i++)
		{
			float left_x = i * getMeasuredWidth();
			float right_x = left_x + getMeasuredWidth();
			
			if (left_x < at_view_point && right_x > at_view_point) {
				currIndex = i;
			}
		}
	
		return currIndex;
	}
	private float getViewCenterPoint() 
	{
		float half_size = getMeasuredWidth() / 2;	// ÇÑÀåÀÇ È­¸éÀÇ Àý¹Ý Å©±â
		float horizontal_x = getHorizontal_x();		// È­¸é¿¡¼­ ¸Ç ¿ÞÂÊ
		float at_view_point = horizontal_x + half_size; // »ç¿ëÀÚ°¡ º¸°í ÀÖ´Â À§Ä¡ : (¸Ç ¿ÞÂÊ + Àý¹Ý Å©±â)
		
		return at_view_point;
	}
	//
	

	private final boolean D = true;
	private final String TAG = "HFlingerLayout";
	private final String TAG2 = "HFlingerLayout.2";
	
	private long tm_interpolation = 0;
	
	private final double accelerationDelay_ms = 240;//120;
	private static int m_nIndex = 0;
	
	private Handler handler = new Handler();
	private LinearLayout container = null;
	private HorizontalScrollView content_horizontal_container = null;
	private LinearLayout content_item_container = null;
	private Context context = null;
}

